﻿using HPSocket.Tcp;
using HPSocket;
using System.Text;
using System.Windows;
using HPSocketLibrary;
using HPSocket.Ssl;
using System.Collections;
using HPSocketLibrary.Devices;

namespace HPSocketClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ITcpClient<string> server;
        private Timer reconnectTimer;
        private Timer heartbeatTimer;
        private int reconnectInterval = 5000; // 重连间隔时间，单位为毫秒
        private int heartbeatInterval = 3000; // 心跳间隔时间，单位为毫秒
        CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
        //写空闲定时器
        private System.Threading.Timer HeatActiveTimer;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //this.serverIp.Text = System.Net.IPAddress.Any.ToString();


            server = new TcpClient<string>()
            {
                DataReceiveAdapter = new TextDataReceiveAdapter()
            };
            server.OnConnect += OnConnect; //连接事件
            server.OnClose += OnClose;   //断开连接事件
            server.OnPrepareConnect += OnPrepareConnect;// 准备连接了事件
            server.OnParseRequestBody += OnParseRequestBody;
            server.OnHandShake += OnHandShake; //TCP握手成功事件
            server.SocketBufferSize = 40960; // 4K
            server.Async = true; // 异步连接

            // 初始化重连定时器
            reconnectTimer = new Timer(ReconnectTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
            // 初始化心跳定时器
            heartbeatTimer = new Timer(HeartbeatTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
            ConsoleHelper.writeLogHandler += (run) =>
            {
                logParagraph.Inlines.Add(run);
                richTextBox.ScrollToEnd();
            };
        }

        // 心跳定时器回调
        private void HeartbeatTimerCallback(object? state)
        {
            ConsoleHelper.Info($"发送心跳数据包");
            MtMsg_HeatBeat heatBeat = MtMsg_HeatBeat.CreateNewMsg();
            // 发送心跳数据包
            WriteMsg(heatBeat);
        }

        public bool WriteMsg(MtMsg_HeatBeat msg)
        {
            string msgJson = Newtonsoft.Json.JsonConvert.SerializeObject(msg);
            MtSSLMsgType mtype = MtIntfaceMsgFormat_Head.GetMsgType(msg.head.interfaceName);
            msgJson += "\r\n";
            bool isNeedSaveMsg = false;
            if (server.HasStarted)
            {
                var bytes = Encoding.UTF8.GetBytes(msgJson);
                // 发送实际数据, 发送失败断开连接
                if (!server.Send(bytes, bytes.Length))
                {
                    isNeedSaveMsg = true;
                    server.Stop();
                }
            }
            else isNeedSaveMsg = true;

            return !isNeedSaveMsg;
        }
        private HandleResult OnParseRequestBody(IClient sender, IntPtr connId, string obj)
        {
            Task.Factory.StartNew(() =>
            {
                MsgRote(obj);
            });
            return HandleResult.Ok;
        }
        private void MsgRote(string msg)
        {
            ConsoleHelper.Info($"接收到的数据={msg}");
        }
        /// <summary>
        /// 数据包发送事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        private HandleResult OnSend(IClient sender, byte[] data)
        {
            ConsoleHelper.Info(string.Format("TCP客户端发送数据到TCP服务器[{0}]{1}:{2};数据内容[长度{3}]：{4}", sender.ConnectionId, sender.Address, sender.Port, data.Length, Encoding.UTF8.GetString(data)));
            return HandleResult.Ok;
        }
        /// <summary>
        /// TCP握手成功事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <returns></returns>
        private HandleResult OnHandShake(IClient sender)
        {
            ConsoleHelper.Info($"Handshake with client {sender.ConnectionId}.");
            // 在这里可以执行自定义的握手逻辑

            // 返回 HandleResult.Ok 表示握手成功
            return HandleResult.Ok;
        }
        public bool StarClient()
        {
            if (server.HasStarted && server.IsConnected)
            {
                return true;
            }
            else
            {
                server.Connect();
                return server.IsConnected;
            }
        }
        public void StopClient()
        {
            cancelTokenSource.Cancel();
            server.Stop();
            try
            {
                if (HeatActiveTimer != null)
                {
                    //终止心跳计时器
                    HeatActiveTimer.Dispose();
                }
            }
            catch
            { }
        }

        /// <summary>
        /// 准备连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="socket"></param>
        /// <returns></returns>
        private HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
        {
            ConsoleHelper.Info($"准备连接 ({sender.Address}:{sender.Port}), socket handle: {socket}, hp-socket version: {sender.Version}");

            return HandleResult.Ok;
        }


        /// <summary>
        /// 连接事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <returns></returns>
        private HandleResult OnConnect(IClient sender)
        {
            ConsoleHelper.Info($"连接成功时重置重连定时器");
            // 连接成功时重置重连定时器
            reconnectTimer.Change(Timeout.Infinite, Timeout.Infinite);
            // 启动心跳定时器
            heartbeatTimer.Change(heartbeatInterval, heartbeatInterval);
            ConsoleHelper.Info($"新的Socket Client IP：{sender.Address} 端口：{sender.BindPort} connId：{sender.ConnectionId}");
            return HandleResult.Ok;
        }

        private void StartBtn_Click(object sender, RoutedEventArgs e)
        {
            logParagraph.Inlines.Clear();
            ushort port = (ushort)serverPort.Text.ToInt32();

            server.Address = this.serverIp.Text;// 设置服务端IP
            if (port == 0)
                port = 902;
            server.Port = port;// 设置端口

            if (StartBtn.Tag.ToInt() == 0)
            {

                if (StarClient())
                {
                    // 启动成功
                    this.StartBtn.Tag = 1;
                    this.StartBtn.Content = "断开连接";
                }
                else
                {
                    // 启动失败
                    ConsoleHelper.Error($"error code: {server.ErrorCode}, error message: {server.ErrorMessage}");
                }
            }
            else
            {

                StopClient();
                server.OnPrepareConnect -= OnPrepareConnect;  // 准备连接了事件
                server.OnConnect -= OnConnect;                // 连接事件
                server.OnHandShake -= OnHandShake;            // TCP握手成功事件
                server.OnSend -= OnSend;                      // 数据包发送事件
                server.OnParseRequestBody -= OnParseRequestBody;                // 数据包到达事件
                server.OnClose -= OnClose;                    // TCP连接关闭事件
                this.StartBtn.Tag = 0;
                this.StartBtn.Content = "开始连接";
            }
        }

        /// <summary>
        /// 关闭连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="socketOperation"></param>
        /// <param name="errorCode"></param>
        /// <returns></returns>
        private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
        {
            // 启动重连定时器
            reconnectTimer.Change(reconnectInterval, Timeout.Infinite);
            // 停止心跳定时器
            heartbeatTimer.Change(Timeout.Infinite, Timeout.Infinite);
            string _errorMsg = "";
            switch (errorCode)
            {
                case 0:
                    {
                        _errorMsg = "客户端主动断开";
                    }
                    break;
                case 10054:
                    {
                        _errorMsg = "客户端异常断开";
                    }
                    break;
                case 10061:
                    {
                        _errorMsg = "连接被对方拒绝";
                    }
                    break;
                case 10053:
                    {
                        _errorMsg = "服务已关闭";
                    }
                    break;
            }
            this.Dispatcher.Invoke(() =>
            {
                this.StartBtn.Tag = 0;
                this.StartBtn.Content = "开始连接";
            });
            ConsoleHelper.Info($"Socket Client连接断开 connId：{sender.ConnectionId} errorCode：{errorCode} {_errorMsg}");
            return HandleResult.Ok;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {

            if (server.HasStarted)
            {
                MessageBox.Show(@"请先停止服务", @"服务正在运行:", MessageBoxButton.OK, MessageBoxImage.Warning);
                e.Cancel = true;
                return;
            }
            // 停止心跳定时器
            heartbeatTimer.Dispose();
            // 停止重连定时器
            reconnectTimer.Dispose();
            // 停止释放服务器
            server.Dispose();
        }

        private void SendBtn_Click(object sender, RoutedEventArgs e)
        {
            string hostname = this.serverIp.Text;
            int port = int.Parse(this.serverPort.Text);
            string sendMsg = this.txtMsg.Text;
            if (string.IsNullOrEmpty(sendMsg))
            {
                ConsoleHelper.Error("发送信息不可为空！");
                return;
            }

            try
            {
                MtMsg_HeatBeat heatBeat = MtMsg_HeatBeat.CreateNewMsg();
                bool resultData_TCP = WriteMsg(heatBeat);
            }
            catch (Exception ex)
            {
                ConsoleHelper.Error("TCPServer服务器广播内容中止！错误信息：" + ex.Message);
            }
        }
        // 重连定时器回调
        private void ReconnectTimerCallback(object? state)
        {
            // 执行重连操作
            bool result = server.Connect();
            if (result)
            {
                this.Dispatcher.Invoke(() => {
                    // 启动成功
                    this.StartBtn.Tag = 1;
                    this.StartBtn.Content = "断开连接";
                });
                // 重连成功时重置重连定时器
                ConsoleHelper.Info($"重连成功时重置重连定时器");
                reconnectTimer.Change(Timeout.Infinite, Timeout.Infinite);
            }
            else
            {
                // 启动成功
                this.StartBtn.Tag = 0;
                this.StartBtn.Content = "开始连接";
                ConsoleHelper.Error($"重连失败，继续等待下一次重连");
                // 重连失败，继续等待下一次重连
                reconnectTimer.Change(reconnectInterval, Timeout.Infinite);
            }
        }
    }
}